package src.application.Doppelkopf;

import src.application.Doppelkopf.Spieler;

/**
 * Klasse die eine Spielrunde Doppelkopf verwaltet.
 *
 * @author Lucksch
 */
public class Spielrunde {

    /**
     * Punkte die jeder der 4 Spieler bis jetzt in einem Spiel durch gewonnene
     * Stiche erzielt hat
     */
    private int rundenPkt[];
    /**
     * Punkte jedes Spielers, die er durch den Gewinn eines Spiels erhaelt
     */
    private int tunierPkt[];
    /**
     * Array, in dem die vier Spieler gespeichert sind
     */
    private Spieler spieler[];
    /**
     * Array, in dem die gespielten Karten eines Stich gespeichert sind(in der
     * Reihenfolge wie sie gelegt wurden)
     */
    private Karte stich[];
    /**
     * Zahlenwert, der angibt, wer das Aufspiel beim naechsten Stich hat
     */
    private Deck d1;
    private int aufspiel;
    /**
     * Zahlenwert, der angibt, wer das naechste Spiel beginnt(geber+1)
     */
    private int geber;
    /**
     * Zahlenwert, der angibt, wie viele Stiche bereits gespielt wurden(ein
     * Spiel besteht aus 10 Stichen)
     */
    private int stichanzahl=0;
    /**
     * Character, der angibt, ob der letzte Stich mit dem KreuzBuben gewonnen
     * wurde und von welcher Partei('r' fuer Re, 'k' fuer kontra, ' ' fuer kein
     * Karlchen)(Karlchen, 1 Extrapunkt)
     */
    private char karlchen= ' ';
    /**
     * Array mit zwei Elementen, in gespeichert wird, ob die Parteien einen
     * Doppelkopf(Stich mit mind 40 Punkten) gewonnen haben. Die erste Position
     * im Array steht dabei für die Anzahl der Doppelkoepfe der Re-Partei, die
     * zweite fuer die der Kontra-Partei. (Pro Doppelkopf einen Extrapunkt)
     */
    private int doppelkopf[]= {0,0};
    /**
     * Array mit zwei Elementen, in dem gespeichert wird, ob die Parteien einen
     * oder mehr Fuechse(KaroAss) gefangen haben. Falls im gewonnenen Stich ein
     * KaroAss der Gegner ist, gibts dies einen Extrapunkt. Erste Position steht
     * für die Anzahl der gefangenen Fuechse der Re-Partei, zweite Position fuer
     * die der Kontra-Partei.
     */
    private int fuchsGefangen[] = {0,0};
    /**
     * Character, der angibt ob und welche Partei die Herz10 der Gegner gefangen
     * hat. Falls beide Herz10en in einem Stich gelegt werden gewinnt, die
     * zuletzt gelegt und "faengt" die erste(1 Extrapunkt). 'r' fuer Re-Partei,
     * 'k' fuer Kontra-Partei, ' ' fuer keine gefangen
     */
    private char herz10gefangen= ' ';

    /**
     * Konstruktor, der die vier Spieler uebergegen bekommt und sie im Array
     * speichert. Als geber wird auf 3 gesetzt(letzter Spieler), sodass der
     * erste Spieler(im Array Spieler[0]) in dieser Spielrunde anfaengt und das
     * Aufspiel hat(aufspiel=0). Es wird ein Kartendeck erstellt und die Karten
     * werden an die 4 Spieler verteilt. Alle uebrigen Attribute werden mit null
     * initialisiert.
     *
     * @param s1 Spieler1
     * @param s2 Spieler2
     * @param s3 Spieler3
     * @param s4 Spieler4
     */
    public Spielrunde(Spieler s1, Spieler s2, Spieler s3, Spieler s4) {
        spieler = new Spieler[4];
        spieler[0] = s1;
        spieler[1] = s2;
        spieler[2] = s3;
        spieler[3] = s4;
        rundenPkt = new int[4];
        tunierPkt = new int[4];
        stich = new Karte[4];
        geber = 3;
        aufspiel = 0;
        stichanzahl = 0;

        d1 = new Deck();
        gebeKarten(d1);
    }
    
    public void reset(){
        rundenPkt = new int[4];
        tunierPkt = new int[4];
        stich = new Karte[4];
        geber = (geber+1)%4;
        aufspiel = (geber+1)%4;
        stichanzahl = 0;

        d1 = new Deck();
        gebeKarten(d1);
        
        stich = new Karte[4];
        karlchen= ' ';
        doppelkopf[0]= 0; doppelkopf[1]= 0;
        fuchsGefangen[0]=0; fuchsGefangen[1]=0;
        herz10gefangen= ' ';
    }

    public void setStich(Karte k1, Karte k2, Karte k3, Karte k4) {
        stich[0] = k1;
        stich[1] = k2;
        stich[2] = k3;
        stich[3] = k4;
    }

    public void setSpielart(int spielart) {
        d1.setTrumpf(spielart);
    }

    public Karte[] getStich() {
        return stich;
    }

    public int getaufspieler() {
        return aufspiel;
    }

    /**
     * Diese Methode verwaltet einen Stich. Der Stichgewinner wird ermittelt,
     * das Aufspiel fuer den naechsten Stich wird gesetzt, der Wert des Stiches
     * wird ermittelt und zum Punktekonto des Stichgewinners addiert. Außerdem
     * wird ueberprueft ob der Stich ein Doppelkopf war, was einen Extrapunkt
     * fuer die Partei des Stichgewinners bringt.
     */
    public void spieleStich() {
        //bestimmt die Nummer des Stichgewinners(in Abhängigkeit zum Array spieler) 
        int nummerGewinner = stichGewinner();
        //setzt das Aufspiel zum nächsten Stich auf die Nummer des Spielers der gewonnen hat
        aufspiel = nummerGewinner;
        //erhöht die Rundenpunkte des Spielers der gewonnen hat, um die Anzahl der Punkte des stichs
        int stichWert = bestimmeStichWert();

        if (stichWert >= 40) {
            if (spieler[nummerGewinner].getRe() == true) {
                doppelkopf[0]++;
            } else {
                doppelkopf[1]++;
            }
        }
        rundenPkt[nummerGewinner] += stichWert;
    }

    /**
     * Die Methode ermittelt den Gewinner des Spiels. Die Punkte der jeweiligen
     * Parteien werden zusammengezaehlt. Dann werden die Punkte berechnet, die
     * die Gewinner Partei erhaelt und zu deren bisherigen Punkten
     * addiert.(ACHTUNG: Sonderpunkte und Vorbehalte werden bis jetzt noch nicht
     * beruecksichtigt)
     *
     * @return gewinner Array in den steht welche Spieler gewonnen
     * haben(true=gewonnen)
     */
    public boolean[] spielGewinner() {
        int punkteRe = 0;
        int punkteKon = 0;
        boolean[] gewinner = {false, false, false, false};
        for (int i = 0; i < 4; i++) {
            if (spieler[i].getRe() == true) {
                punkteRe += rundenPkt[i];
            } else {
                punkteKon += rundenPkt[i];
            }
        }
        //die Re Partei hat gewonnen
        if (punkteRe >= 121) {
            for (int i = 0; i < 4; i++) {
                if (spieler[i].getRe() == true) {
                    gewinner[i] = true;
                    tunierPkt[i]++;
                } else {
                    gewinner[i] = false;
                }
            }

        }// die Kontra Partei hat gewonnen
        else if (punkteKon >= 120) {
            for (int i = 0; i < 4; i++) {
                if (spieler[i].getRe() == false) {
                    gewinner[i] = true;
                    tunierPkt[i]+= 2;
                } else {
                    gewinner[i] = false;
                }

            }
        }
        karlchen = ' ';
        herz10gefangen = ' ';
        doppelkopf[0] = 0;
        doppelkopf[1] = 0;
        fuchsGefangen[0] = 0;
        fuchsGefangen[1] = 0;

        geber = (geber + 1) % 4;
        aufspiel = geber + 1;
        return gewinner;
    }

    /**
     * Bestimmt den Punktewert eines gespieltes Stiches.
     *
     * @return wert Zahlenwert, der dem Wert des Stichs entspricht
     */
    public int bestimmeStichWert() {
        int wert = 0;
        for (Karte alle : stich) {
            wert += alle.getWert();
        }
        return wert;
    }

    /**
     * Die Methode ermittelt den Gewinner des Stichs. Ausserdem wird geprueft,
     * ob eine Herz10 oder ein Fuchs gefangen wurde und ob im letzten Stich ein
     * Karlchen gemacht wurde(alles Extrapunkte).
     *
     * @return gibt den gewinner des Stichs zurueck(die Position die der
     * Gewinner im Array spieler hat)
     */
    private int stichGewinner() {
        Spieler gewinner;
        stichanzahl++;
        int pos = 0;
        int anzahlHerz10 = 0;
        char fuchsgelegt[] = new char[4];
        //erste gespielte Karte ist zu Anfang des Stichs die hoechste
        Karte stichgew = stich[0];


        //Schleife über die restlichen Karten des Stichs(ACHTUNG:karte wird doch noch mit sich selbst verglichen)
        for (int i = 0; i < 4; i++) {
            //hier wird abgefragt, ob eine herz10 über eine Andere gelegt wurde.
            //Falls ja, ist die 2. die höhere und die Partei, die sie gelegt hat bekommt einen extra Punkt
            if (stich[i].trumpfOrder() == 11) {
                anzahlHerz10++;
                if (anzahlHerz10 == 2) {
                    stichgew = stich[i];
                    pos = i;
                    if (spieler[i].getRe() == true) {
                        herz10gefangen = 'r';
                    } else {
                        herz10gefangen = 'k';
                    }
                    return (aufspiel + pos) % 4;
                }
            }
            //hier wird geprüft ob ein fuchs gelegt wurde und von welcher Partei
            if (stich[i].trumpfOrder() == 2) {
                if (spieler[i].getRe() == true) {
                    fuchsgelegt[i] = 'r';
                } else {
                    fuchsgelegt[i] = 'k';
                }
            }

            //falls die neue Karte von stapel hoeher als der akt Stichgewinner ist
            //(Rueckg:-1), dann wird der Stichgewinner neu gesetzt
            if (stichgew.compareStichkarten(stich[i]) == -1) {
                stichgew = stich[i];
                pos = i;
                System.out.println("Hier wurde eine hoehere Karte gelegt: " + pos);
            }
        }

        gewinner = spieler[(aufspiel + pos) % 4];
        //prüft ob der letzte Stich(stichanzahl==10) mit einem kreuz Buben gewonnen wurde->extra Punkt
        if (stichanzahl == 10 && stichgew.trumpfOrder() == 6) {
            if (gewinner.getRe() == true) {
                karlchen = 'r';
            } else {
                karlchen = 'k';
            }
        }

        //hier wird geprüft welche partei einen Fuchs gefangen hat oder ob er sogar im letzten 
        //stich gefangen wurde(2 extrapunkte)
        if (gewinner.getRe() == true) {
            for (int i = 0; i < 4; i++) {
                if (fuchsgelegt[i] == 'k') {
                    if (stichanzahl == 10) {
                        fuchsGefangen[0] += 2;
                    } else {
                        fuchsGefangen[0]++;
                    }
                }
            }
        } else {
            for (int i = 0; i < 4; i++) {
                if (fuchsgelegt[i] == 'r') {
                    if (stichanzahl == 10) {
                        fuchsGefangen[1] += 2;
                    } else {
                        fuchsGefangen[1]++;
                    }
                }
            }
        }


        return (aufspiel + pos) % 4;
    }

    /**
     * Die Methde, verteilt alle Karten des Decks an die vier Spieler.
     *
     * @param d Doppelkopf Kartendeck mit 40 Karten
     */
    private void gebeKarten(Deck d) {
        //karten mischen
        d.mische();

        int i, j;
        for (j = 0; j < 10; j++) {
            for (i = 0; i < 4; i++) {
                spieler[i].handkarten[j] = d.ziehe();
                if (j == 9) {
                    java.util.Arrays.sort(spieler[i].handkarten);
                }
            }
        }

        /*for (j=0; j<3; j++)
         spieler[i].handkarten[j]= d.ziehe();
         for (j=3; j<7; j++)
         spieler[i].handkarten[j]= d.ziehe();
         for (j=7; j<10; j++)
         spieler[i].handkarten[j]= d.ziehe(); */

    }
}
